
package com.xuyanze.core.manager;

import com.alibaba.fastjson.JSON;
import com.xuyanze.core.factory.Function;
import com.xuyanze.model.PathModel;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ：lzy
 * @date ：2022-04-25
 * @description：
 */

public class PathManager {
    private Map<String,PathModel.Data> pathMap = new LinkedHashMap<>();
    private boolean modify = false;
    private volatile boolean init = false;

    public static final String SEPARATOR = File.separator;
    public static final String SEPARATOR_DOUBLE = SEPARATOR + SEPARATOR;
    public static final String USER_DIR = System.getProperty("user.dir");
    public String classesPath= String.format("%s%starget%sclasses%sdoc%sdoc.json",USER_DIR,SEPARATOR_DOUBLE,SEPARATOR_DOUBLE,SEPARATOR_DOUBLE,SEPARATOR_DOUBLE);
    public String resourcesPath=String.format("%s%ssrc%smain%sresources%sdoc%sdoc.json",USER_DIR,SEPARATOR_DOUBLE,SEPARATOR_DOUBLE,SEPARATOR_DOUBLE,SEPARATOR_DOUBLE,SEPARATOR_DOUBLE);

    private static class Instance{
        static PathManager pathManager = new PathManager();
    }

    private PathManager(){
        this.loading();
    }

    public static PathManager getInstance(){
        return Instance.pathManager;
    }

    public synchronized void loading(){
        if(init) return;
        openFileChannel(resourcesPath,(randomAccessFile,channel)->{
            FileChannel fileChannel = (FileChannel)channel;
            try {
                ByteBuffer allocate = ByteBuffer.allocate((int)fileChannel.size());
                fileChannel.read(allocate);
                if(allocate.position() == 0){
                    return;
                }

                String text = new String(allocate.array());
                PathModel pathModel = JSON.parseObject(text, PathModel.class);
                for (PathModel.Data data : pathModel.getDatas()) {
                    pathMap.put(data.getUrl(),data);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                init = true;
            }
        });

    }

    public void put(String url,String pid){
        if(!pathMap.containsKey(url)){
            PathModel.Data data = new PathModel.Data();
            data.setUrl(url);
            data.setPid(pid);
            pathMap.put(url,data);
            modify = true;
        }
    }

    /**
     * 路径资源id
     * @param key
     * @return
     */
    public String getPid(String key){
        PathModel.Data data = pathMap.get(key);
        return data !=null ? data.getPid() : null;
    }

    public boolean isModify(){
        return modify;
    }

    public void write(){
        openFileChannel(resourcesPath,(randomAccessFile,channel)->{
            PathModel pathModel = new PathModel();
            pathModel.setDatas((new ArrayList<>( pathMap.values())));
            String json = JSON.toJSONString(pathModel,true);
            FileChannel fileChannel = (FileChannel)channel;
            try {
                ByteBuffer allocate = ByteBuffer.allocate(json.getBytes().length);
                allocate.put(json.getBytes());
                allocate.flip();
                randomAccessFile.setLength(0);
                fileChannel.write(allocate);
                fileChannel.force(true);
            } catch (IOException e) {
                e.printStackTrace();
            }

        });
    }

    public void flush(){
        write();
//        copyTargetDict();
    }

    private void openFileChannel(String path, Function function){
        try {
            File file = new File(path);
            if(!file.exists()) {
                File parentFile = file.getParentFile();
                parentFile.mkdirs();
                file.createNewFile();
            }
            RandomAccessFile inputStream1 = new RandomAccessFile(file,"rw");
            FileChannel channel1 = inputStream1.getChannel();
            function.apply(inputStream1,channel1);
            inputStream1.close();
            channel1.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void copyTargetDict(){
        try {
            FileInputStream inputStream0 = new FileInputStream(new File(resourcesPath));
            FileChannel channel0 = inputStream0.getChannel();
            File file = new File(classesPath);
            if(!file.exists()) {
                File parentFile = file.getParentFile();
                parentFile.mkdirs();
                file.createNewFile();
            }

            if(!file.exists()) file.createNewFile();
            RandomAccessFile inputStream1 = new RandomAccessFile(file,"rw");
            FileChannel channel1 = inputStream1.getChannel();
            channel0.transferTo(0,channel0.size(),channel1);

            inputStream0.close();
            channel0.close();
            inputStream1.close();
            channel1.close();
        }catch (IOException e) {
            e.printStackTrace();
        }

    }
}
